package com.kaifamiao.collection;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

/**
 * 实现 java.util.Collection 接口并指定 类型参数 为 Object
 */
public class Container implements Collection<Object>{
	
	// 约定默认容量
	private static final int DEFAULT_CAPACITY = 10 ;
	// 约定默认加载因子
	private static final float DEFAULT_LOAD_FACTOR = 0.75F ;
	// 用来存放元素的数组
	private Object[] elements ;
	// 用来记录集合中所存放的元素个数
	private int counter ;
	// 加载因子(用于确定什么时候对elements数组扩容)
	private float loadFactor ;
	
	public Container() {
		this( DEFAULT_CAPACITY , DEFAULT_LOAD_FACTOR );
	}
	
	public Container( int initialCapacity ) {
		this( initialCapacity , DEFAULT_LOAD_FACTOR );
	}
	
	public Container( int initialCapacity , float loadFactor ) {
		super();
		if( initialCapacity < 0 ) {
			throw new IllegalArgumentException( "集合容量必须大于零" );
		}
		if( loadFactor <= 0 || loadFactor >= 1 ) {
			throw new IllegalArgumentException( "加载因子必须是0到1之间的浮点数" );
		}
		// 根据指定的初始容量来创建数组对象
		this.elements = new Object[ initialCapacity ];
		// 根据参数设置加载因子
		this.loadFactor = loadFactor ;
	}
	
	public Container( Collection<? extends Object> c ) {
		this( DEFAULT_CAPACITY , DEFAULT_LOAD_FACTOR );
		// 将参数传入的集合中的所有元素添加到当前集合中
		this.addAll( c );
	}
	
	// 用于对数组扩容的方法
	private void ensureCapacity() {
		// 确定是否需要扩容
		if( counter >= elements.length * loadFactor ) {
			Object[] temp = elements ;// 用临时变量缓存原数组
			int newLength = temp.length * 3 / 2 + 1 ;
			elements = new Object[ newLength ] ; // 创建新数组
			// 将 temp 数组中 [ 0 , counter ) 之间的元素复制到 elements 数组中
			System.arraycopy( temp , 0 , elements, 0, counter);
		}
	}

	@Override
	public boolean add(Object e) {
		ensureCapacity();
		elements[ counter++ ] = e ;
		return true;
	}

	@Override
	public int size() {
		return counter;
	}

	@Override
	public boolean isEmpty() {
		return counter == 0 ;
	}

	@Override
	public boolean contains(Object o) {
		return this.indexOf( o ) != -1 ;
	}

	@Override
	public void clear() {
		// 将 elements 数组中所有位置 填充为 null
		Arrays.fill( elements ,  null );
		counter = 0 ;
	}

	// 寻找指定元素在集合内数组中的索引
	private int indexOf( Object o ) {
		for( int i = 0 ; i < counter ; i++ ) {
			Object e = elements[ i ];
			if( e == o || ( e != null && e.equals( o ) ) ) {
				return i ; // 若找到则返回相应的索引
			}
		}
		return -1 ; // 若未找到则返回 -1
	}
	
	@Override
	public boolean remove(Object o) {
		int index = this.indexOf(o);
		int b = index + 1 ; // 确定从哪里开始移动元素
		int n = counter - index - 1 ; // 计算需要移动的元素个数
		// 将 elements 数组中的 [ b , b + n ) 之间的元素
		// 复制到 elements 数组的 [ index , counter - 1 ) 之间
		System.arraycopy( elements , b, elements , index , n );
		counter-- ;
		return true;
	}

	@Override
	public Object[] toArray() {
		// 复制 elements 数组中 [ 0 , counter ) 之间的元素到新数组中并返回新数组
		Object[] array = Arrays.copyOfRange( elements,  0 ,  counter );
		return array;
	}
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append( '[' );
		for( int i = 0 ; i < counter ; i++ ) {
			Object e = elements[ i ];
			sb.append( e );
			sb.append( ',' );
		}
		int last = sb.lastIndexOf( "," );
		if( last != -1 ) {
			sb.deleteCharAt( last );
		}
		sb.append( ']' );
		return sb.toString();
	}
	
	@Override
	public boolean addAll(Collection<? extends Object> c) {
		if( c == null ) {
			throw new IllegalArgumentException( "你丫给的集合怎么能是null呢" );
		}
		// 如果集合为空
		if( this.isEmpty() ) {
			Object[] array = c.toArray();
			if( this.elements.length > array.length ) {
				System.arraycopy( array , 0 , elements , 0 , array.length );
			} else {
				this.elements = array ;
			}
			this.counter = array.length ;
			return true;
		}
		
		Object[] array = c.toArray();
		for( int i = 0 , n = array.length ; i < n ; i++ ) {
			this.add( array[ i ] );
		}
		return true ;
	}

	@Override
	public boolean containsAll(Collection<?> c) {
		// 自己实现
		return false;
	}

	@Override
	public boolean removeAll(Collection<?> c) {
		// 自己实现
		return false;
	}

	@Override
	public boolean retainAll(Collection<?> c) {
		// 自己实现
		return false;
	}
	
	@Override
	public Iterator<Object> iterator() {
		// 这个方法不要求实现
		return null;
	}
	
	@Override
	public <T> T[] toArray(T[] a) {
		// 这个方法不要求实现
		return null;
	}

	@Override
	public int hashCode() {
		// 这个方法不要求实现
		return super.hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		// 这个方法不要求实现
		return super.equals(obj);
	}

	
}
